<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h1 data-lake-id="ri7FH" id="ri7FH"><span data-lake-id="uc33dfadd" id="uc33dfadd">典型回答</span></h1>
  <p data-lake-id="u2e1a8fcb" id="u2e1a8fcb"><span data-lake-id="uda97fa00" id="uda97fa00">面对这个问题的时候，读者朋友们可能会有点懵逼，但是我们回到Bean初始化的本质上来看，Bean初始化有两个时机：</span></p>
  <ol list="u760b4f62">
   <li fid="uc7f9db85" data-lake-id="ubbd869a3" id="ubbd869a3"><span data-lake-id="u0aa771ac" id="u0aa771ac">Spring容器主动去初始化该Bean</span></li>
   <li fid="uc7f9db85" data-lake-id="u006ceabc" id="u006ceabc"><span data-lake-id="u450c023c" id="u450c023c">其他Bean依赖该Bean，该Bean会先被初始化</span></li>
  </ol>
  <p data-lake-id="u34252227" id="u34252227"><span data-lake-id="u8bdfa5ff" id="u8bdfa5ff">从这两个出发点来思考解决问题方案的话，大概有如下几种方式：</span></p>
  <h3 data-lake-id="aHYHU" id="aHYHU"><span data-lake-id="u612f9734" id="u612f9734">直接依赖某Bean</span></h3>
  <p data-lake-id="ub2dd3870" id="ub2dd3870"><span data-lake-id="u84d9f1f5" id="u84d9f1f5">如下代码所示：</span></p>
  <pre lang="java"><code>
@Component
public class A {

    @Autowired
    private B b;
}
</code></pre>
  <p data-lake-id="u40a017fc" id="u40a017fc"><span data-lake-id="u1a84a851" id="u1a84a851">如上，在加载Bean A的时候，一定会先初始化Bean B</span></p>
  <h3 data-lake-id="gZpdC" id="gZpdC"><span data-lake-id="u3ab945af" id="u3ab945af">DependsOn</span></h3>
  <p data-lake-id="uf17e452b" id="uf17e452b"><span data-lake-id="u0c1ef5b1" id="u0c1ef5b1">对于应用之外的二方或者三方库来说，因为我们不能修改外部库的代码，如果想要二方库的Bean在初始化之前就初始化我们内部的某个bean，就不能用第一种直接依赖的方式，可以使用</span><code data-lake-id="u9baac074" id="u9baac074"><span data-lake-id="u31089bb8" id="u31089bb8">@DependsOn</span></code><span data-lake-id="u417beb57" id="u417beb57">注解来完成，如下代码所示：</span></p>
  <pre lang="java"><code>
@Configuration
public class BeanOrderConfiguration {

    @Bean
    @DependsOn("beanB")
    public BeanA beanA(){
        return new BeanA();
    }
}
</code></pre>
  <p data-lake-id="u73071d6b" id="u73071d6b"><span data-lake-id="u54e4abe8" id="u54e4abe8">当然，DependsOn注解也可以作用在</span><code data-lake-id="u1ebe71c5" id="u1ebe71c5"><span data-lake-id="ub7f4dc9a" id="ub7f4dc9a">@Component</span></code><span data-lake-id="u37dc815c" id="u37dc815c">注解上面</span></p>
  <h3 data-lake-id="kd35H" id="kd35H"><span data-lake-id="ue342bc3c" id="ue342bc3c">BeanFactoryPostProcessor</span></h3>
  <p data-lake-id="u6f97ddd1" id="u6f97ddd1"><span data-lake-id="u33846902" id="u33846902">前两种方式只能对于特定的Bean生效，如果我们希望某个Bean在其他所有Bean加载之前就初始化，用前面两种方式显然是不合适的，我们这个时候，就需要从Spring容器的生命周期中去找方法。</span></p>
  <p data-lake-id="u24b11210" id="u24b11210"><span data-lake-id="u844ac10c" id="u844ac10c">通过上面的参考文章我们可以知道，Spring的Bean在初始化之前，会通过</span><code data-lake-id="ua33a6b32" id="ua33a6b32"><span data-lake-id="u46454b0a" id="u46454b0a">BeanFactoryPostProcessor#postProcessBeanFactory</span></code><span data-lake-id="ua2e90111" id="ua2e90111">对工厂进行处理，我们可以依赖这个特性，在此刻提前初始化我们需要的bean</span></p>
  <pre lang="java"><code>
@Component
public class PrimaryBeanProcessor implements BeanFactoryPostProcessor {


    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        PrimaryBean bean = beanFactory.getBean(PrimaryBean.class);
        System.out.println(bean);
    }
}
@Component
public class PrimaryBean {

    public PrimaryBean() {
        System.out.println("init primary bean");
    }

    @Override
    public String toString() {
        return "PrimaryBean{aaa}";
    }
}
</code></pre>
  <p data-lake-id="uea903cce" id="uea903cce"><span data-lake-id="ua7ea3e16" id="ua7ea3e16">这个时候我们通过控制台发现，PrimaryBean的初始化等级会优于其他Bean，如下所示：</span></p>
  <pre lang="java"><code>
  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v2.5.2)

2023-05-21 14:32:09.499  INFO 59380 --- [           main] cn.wxxlamp.spring.boot.Main              : Starting Main using Java 1.8.0_291 on B-13CKQ05P-0131.local with PID 59380 (/Users/chenkai/code/test/target/classes started by chenkai in /Users/chenkai/code/test)
2023-05-21 14:32:09.503  INFO 59380 --- [           main] cn.wxxlamp.spring.boot.Main              : No active profile set, falling back to default profiles: default
init primary bean // 希望初始化的Bean
PrimaryBean{aaa}
aware applicationContext // 系统配置Bean
initializingBean
</code></pre>
  <h3 data-lake-id="TzxoR" id="TzxoR"><span data-lake-id="uc53f79ab" id="uc53f79ab">踩坑陷阱</span></h3>
  <p data-lake-id="ub1f870cf" id="ub1f870cf"><span data-lake-id="u760c9967" id="u760c9967">Order只能控制同一个Bean类型中集合的顺序，不能控制不同Bean的初始化顺序，举个例子：</span></p>
  <pre lang="java"><code>
@Component
public class Container {

	private final List&lt;Bean&gt; beanList;
    
    public Container(List&lt;Bean&gt; beanList) {
        this.beanList = beanList;
    }
}
@Order(1)
@Component
class BeanA implements Bean {}
@Order(2)
@Component
class BeanB implements Bean {}
</code></pre>
  <p data-lake-id="ua809f979" id="ua809f979"><span data-lake-id="ue2b9cca1" id="ue2b9cca1">这样在读取的时候，beanList中，BeanA的顺序是先于BeanB的。</span></p>
 </body>
</html>